package org.rcgwt.client.ui.grid.theme;

import java.util.List;

import org.rcgwt.client.theme.CssStyle;
import org.rcgwt.client.ui.grid.controller.DefaultGridController;
import org.rcgwt.client.ui.grid.controller.DefaultViewController;
import org.rcgwt.client.ui.grid.controller.IElementModelEventController;
import org.rcgwt.client.ui.grid.controller.IGridModelController;
import org.rcgwt.client.ui.grid.controller.IHeaderController;
import org.rcgwt.client.ui.grid.controller.IViewController;
import org.rcgwt.client.ui.grid.controller.RowModelEventController;
import org.rcgwt.client.ui.grid.controller.TitleCellEventController;
import org.rcgwt.client.ui.grid.internal.model.ICellModel;
import org.rcgwt.client.ui.grid.internal.model.IColumnModel;
import org.rcgwt.client.ui.grid.internal.model.IElementModel;
import org.rcgwt.client.ui.grid.internal.model.IGridModel;
import org.rcgwt.client.ui.grid.internal.model.IGroupModel;
import org.rcgwt.client.ui.grid.internal.model.IGroupTitleModel;
import org.rcgwt.client.ui.grid.internal.model.IHeaderModel;
import org.rcgwt.client.ui.grid.internal.model.IRowModel;
import org.rcgwt.client.ui.grid.internal.model.IStateMasks;
import org.rcgwt.client.ui.grid.internal.model.ITitleCellModel;
import org.rcgwt.client.ui.grid.internal.model.ITitleRowModel;
import org.rcgwt.client.ui.grid.internal.model.IViewModel;
import org.rcgwt.client.ui.grid.model.IColumn;
import org.rcgwt.client.ui.grid.model.IGridWidget;
import org.rcgwt.client.ui.grid.provider.BasicFocusProvider;
import org.rcgwt.client.ui.grid.provider.BasicOrderProvider;
import org.rcgwt.client.ui.grid.provider.BasicOverProvider;
import org.rcgwt.client.ui.grid.provider.IFocusProvider;
import org.rcgwt.client.ui.grid.provider.IOrderProvider;
import org.rcgwt.client.ui.grid.provider.IOverProvider;
import org.rcgwt.client.ui.grid.renderer.DefaultCellRenderer;
import org.rcgwt.client.ui.grid.renderer.DefaultGridRenderer;
import org.rcgwt.client.ui.grid.renderer.DefaultGroupRenderer;
import org.rcgwt.client.ui.grid.renderer.DefaultHeaderRenderer;
import org.rcgwt.client.ui.grid.renderer.DefaultRowRenderer;
import org.rcgwt.client.ui.grid.renderer.DefaultTitleCellRenderer;
import org.rcgwt.client.ui.grid.renderer.DefaultTitleRowRenderer;
import org.rcgwt.client.ui.grid.renderer.DefaultViewRenderer;
import org.rcgwt.client.ui.grid.renderer.ICellEditorRenderer;
import org.rcgwt.client.ui.grid.renderer.ICellRenderer;
import org.rcgwt.client.ui.grid.renderer.IGridRenderContext;
import org.rcgwt.client.ui.grid.renderer.IGridRenderer;
import org.rcgwt.client.ui.grid.renderer.IGroupRenderer;
import org.rcgwt.client.ui.grid.renderer.IGroupTitleRenderer;
import org.rcgwt.client.ui.grid.renderer.IHeaderRenderer;
import org.rcgwt.client.ui.grid.renderer.IPopupRenderer;
import org.rcgwt.client.ui.grid.renderer.IRowRenderer;
import org.rcgwt.client.ui.grid.renderer.ITitleCellRenderer;
import org.rcgwt.client.ui.grid.renderer.ITitleRowRenderer;
import org.rcgwt.client.ui.grid.renderer.IViewRenderContext;
import org.rcgwt.client.ui.grid.renderer.IViewRenderer;

/**
 * Manage the setting for interface style
 * 
 * @author Matthieu ROBERT & Olivier Oeuillot
 * 
 */
public class DefaultGridTheme implements IGridTheme {

	private static IGridTheme instance = new DefaultGridTheme();

	public static IGridTheme getTheme() {
		return instance;
	}

	public static void setTheme(IGridTheme theme) {
		instance = theme;
	}

	/**
	 * The default style name.
	 */
	public static final String DEFAULT_STYLE_NAME = "rcgwt-grid";

	private CssStyle gridCssStyle;

	private CssStyle gridThemeCssStyle;

	// Header
	// public static final String DEFAULT_TITLE_STYLE_NAME = DEFAULT_STYLE_NAME+
	// "-head";

	// private CssStyle titleStyleName;

	// Title Row
	public static final String DEFAULT_TITLE_ROW_STYLE_NAME = DEFAULT_STYLE_NAME
			+ "-title-row";

	private CssStyle titleRowCssStyle;

	// Title Cell
	public static final String DEFAULT_TITLE_CELL_STYLE_NAME = DEFAULT_STYLE_NAME
			+ "-title-cell";

	private CssStyle titleCellCssStyle;

	public static final String DEFAULT_TITLE_CELL_DRAGGER_STYLE_NAME = DEFAULT_STYLE_NAME
			+ "-title-cell-dragger";

	private CssStyle titleCellSizeDraggerCssStyle;

	public static final String DEFAULT_TITLE_CELL_ORDER_MARKER_STYLE_NAME = DEFAULT_STYLE_NAME
			+ "-title-cell-orderMarker";

	private CssStyle titleCellOrderMarkerCssStyle;

	public static final String DEFAULT_TITLE_CELL_POPUP_MARKER_STYLE_NAME = DEFAULT_STYLE_NAME
			+ "-title-cell-popupMarker";

	private CssStyle titleCellPopupMarkerCssStyle;

	public static final String DEFAULT_TITLE_CELL_TEXT_STYLE_NAME = DEFAULT_STYLE_NAME
			+ "-title-cell-text";

	private CssStyle titleCellTextCssStyle;

	// Body

	// public static final String DEFAULT_BODY_STYLE_NAME = DEFAULT_STYLE_NAME+
	// "-body";

	// private CssStyle bodyStyleName;

	// Table
	public static final String DEFAULT_TABLE_STYLE_NAME = DEFAULT_STYLE_NAME
			+ "-table";

	private CssStyle tableCssStyle;

	// Group
	public static final String DEFAULT_GROUP_STYLE_NAME = DEFAULT_STYLE_NAME
			+ "-group";

	private CssStyle groupCssStyle;

	// Group Title
	public static final String DEFAULT_GROUP_TITLE_STYLE_NAME = DEFAULT_STYLE_NAME
			+ "-groupTitle";

	private CssStyle groupTitleCssStyle;

	// Row
	public static final String DEFAULT_ROW_STYLE_NAME = DEFAULT_STYLE_NAME
			+ "-row";

	private CssStyle rowCssStyles[];

	// Cell
	public static final String DEFAULT_CELL_STYLE_NAME = DEFAULT_STYLE_NAME
			+ "-cell";

	private CssStyle cellCssStyles[];

	// View

	private CssStyle viewCssStyle;

	public static final String DEFAULT_VIEW_STYLE_NAME = DEFAULT_STYLE_NAME
			+ "-view";

	// Horizontal Header

	private CssStyle headerCssStyle;

	public static final String DEFAULT_HORIZONTAL_HEADER_STYLE_NAME = DEFAULT_STYLE_NAME
			+ "-horizontal-header";

	// Scrolled table container

	private CssStyle scrollableTableContainerCssStyle;

	public static final String DEFAULT_SCROLLABLE_TABLE_CONTAINER_STYLE_NAME = DEFAULT_STYLE_NAME
			+ "-scrollable-table-container";

	private CssStyle focusedTitleRowCssStyle;

	public static final String DEFAULT_FOCUSED_TITLE_ROW_STYLE_NAME = DEFAULT_STYLE_NAME
			+ "-title-row-focused";

	private static final String SELECTION_SUFFIX = "selected";

	private static final String CHECKED_SUFFIX = "checked";

	private static final String OPENED_SUFFIX = "opened";

	private static final String HOVER_SUFFIX = "hover";

	private static final String FOCUS_SUFFIX = "focus";

	private static final String ORDER_SUFFIX = "order";

	private static final String CONTENT_FOCUSED_SUFFIX = "cfocus";

	private static final String ASCENDING_SUFFIX = "asc";

	private static final String DESCENDING_SUFFIX = "desc";

	private static final String ADDITIONAL_INFORMATION_SUFIX = "additional";

	private static final int[] GRID_PADDINGS = new int[] { 1, 1, 1, 1 };

	private static final int[] TABLE_MARGINS = new int[] { 1, 1, 1, 1 };

	private IGroupTitleRenderer defaultGroupTitleRenderer;

	private ITitleRowRenderer defaultTitleRowRenderer;

	private ITitleCellRenderer defaultTitleCellRenderer;

	private IHeaderRenderer defaultHeaderRenderer;

	private IViewRenderer defaultViewRenderer;

	private IGroupRenderer defaultGroupRenderer;

	private IRowRenderer defaultRowRenderer;

	private ICellRenderer defaultCellRenderer;

	private ICellEditorRenderer defaultCellEditorRenderer;

	private IPopupRenderer<IColumn> defaultColumnPopupRenderer;

	private IPopupRenderer<IColumn> defaultTitleComboPopupRenderer;

	private IPopupRenderer<IRowModel> defaultRowPopupRenderer;

	private IGridRenderer defaultGridRenderer;

	private IHeaderController headerModelController;

	private IViewController viewModelController;

	protected DefaultGridTheme() {
		defaultRowRenderer = new DefaultRowRenderer();
		defaultTitleRowRenderer = new DefaultTitleRowRenderer();
		defaultGroupRenderer = new DefaultGroupRenderer();
		defaultCellRenderer = new DefaultCellRenderer();
		defaultTitleCellRenderer = new DefaultTitleCellRenderer();
		defaultHeaderRenderer = new DefaultHeaderRenderer();
		defaultViewRenderer = new DefaultViewRenderer();
		defaultGridRenderer = new DefaultGridRenderer();

	}

	protected DefaultGridTheme(DefaultGridTheme copy) {
		defaultRowRenderer = copy.defaultRowRenderer;
		defaultTitleRowRenderer = copy.defaultTitleRowRenderer;
		defaultGroupRenderer = copy.defaultGroupRenderer;
		defaultCellRenderer = copy.defaultCellRenderer;
		defaultTitleCellRenderer = copy.defaultTitleCellRenderer;
		defaultHeaderRenderer = copy.defaultHeaderRenderer;
		defaultViewRenderer = copy.defaultViewRenderer;
		defaultGridRenderer = copy.defaultGridRenderer;
	}

	protected IRowRenderer getDefaultRowRenderer() {
		return defaultRowRenderer;
	}

	public IRowRenderer getRowRenderer(IRowModel row) {
		return getDefaultRowRenderer();
	}

	public ITitleRowRenderer getTitleRowRenderer(ITitleRowModel titleRow) {
		return getDefaultTitleRowRenderer();
	}

	protected ITitleRowRenderer getDefaultTitleRowRenderer() {
		return defaultTitleRowRenderer;
	}

	public IGroupTitleRenderer getGroupTitleRenderer(IGroupTitleModel group) {
		return getDefaultGroupTitleRenderer();
	}

	protected IGroupTitleRenderer getDefaultGroupTitleRenderer() {
		return defaultGroupTitleRenderer;
	}

	public IGroupRenderer getGroupRenderer(IGroupModel group) {
		return getDefaultGroupRenderer();
	}

	protected IGroupRenderer getDefaultGroupRenderer() {
		return defaultGroupRenderer;
	}

	protected ICellRenderer getDefaultCellRenderer() {
		return defaultCellRenderer;
	}

	public ICellRenderer getCellRenderer(ICellModel cell) {
		return getDefaultCellRenderer();
	}

	protected ICellEditorRenderer getDefaultCellEditorRenderer() {
		return defaultCellEditorRenderer;
	}

	public ICellEditorRenderer getCellEditorRenderer(IColumnModel columnModel) {
		return getDefaultCellEditorRenderer();
	}

	protected ITitleCellRenderer getDefaultTitleCellRenderer() {
		return defaultTitleCellRenderer;
	}

	public ITitleCellRenderer getTitleCellRenderer(ITitleCellModel titleCell) {
		return getDefaultTitleCellRenderer();
	}

	public IHeaderRenderer getHeaderRenderer(IHeaderModel headerModel) {
		return getDefaultHeaderRenderer();
	}

	protected IHeaderRenderer getDefaultHeaderRenderer() {
		return defaultHeaderRenderer;
	}

	public IViewRenderer getViewRenderer(IViewModel viewModel) {
		return getDefaultViewRenderer();
	}

	protected IViewRenderer getDefaultViewRenderer() {
		return defaultViewRenderer;
	}

	public IGridRenderer getGridRenderer(IGridModel gridModel) {
		return getDefaultGridRenderer();
	}

	protected IGridRenderer getDefaultGridRenderer() {
		return defaultGridRenderer;
	}

	// ------------------- LES STYLES NAMES -------------------------- //
	public CssStyle getGridCssStyle(IGridModel gridModel) {
		if (gridCssStyle == null) {
			gridCssStyle = CssStyle.create(DEFAULT_STYLE_NAME);
		}

		CssStyle style = computeStyleByMask(gridCssStyle, gridModel);

		return style;
	}

	protected String getGridThemeStyleName() {
		return null;
	}

	public CssStyle getGridThemeCssStyle(IGridModel gridModel) {
		if (gridThemeCssStyle == null) {
			String styleName = getGridThemeStyleName();
			if (styleName == null) {
				return null;
			}

			gridThemeCssStyle = CssStyle.create(styleName);
		}

		if (gridThemeCssStyle == null) {
			return null;
		}

		CssStyle cssStyle = computeStyleByMask(gridThemeCssStyle, gridModel);

		return cssStyle;
	}

	public CssStyle getTableStyleName(IViewModel viewModel) {
		if (tableCssStyle == null) {
			tableCssStyle = CssStyle.create(DEFAULT_TABLE_STYLE_NAME);
		}

		int viewHints = viewModel.getRenderHints();

		CssStyle cssStyle = generateScrollCssStyle(tableCssStyle, viewHints);

		cssStyle = computeStyleByMask(cssStyle, viewModel);

		return cssStyle;
	}

	public CssStyle getViewCssStyle(IViewModel viewModel) {
		if (viewCssStyle == null) {
			viewCssStyle = CssStyle.create(DEFAULT_VIEW_STYLE_NAME);
		}

		CssStyle cssStyle = viewCssStyle;

		int viewHints = viewModel.getRenderHints();

		if ((viewHints & (IViewModel.TOP_HEADER | IViewModel.BOTTOM_HEADER
				| IViewModel.LEFT_HEADER | IViewModel.RIGHT_HEADER)) == 0) {
			// Le truc est peut-etre scrollable ...

			cssStyle = generateScrollCssStyle(cssStyle, viewHints);
		}

		cssStyle = computeStyleByMask(cssStyle, viewModel);

		return cssStyle;
	}

	private CssStyle generateScrollCssStyle(CssStyle prefixStyleName, int hints) {

		if ((hints & (IViewModel.HORIZONTAL_SCROLLBAR | IViewModel.VERTICAL_SCROLLBAR)) == 0) {
			return prefixStyleName.addSuffix("no-scroll");

		}

		if ((hints & IViewModel.HORIZONTAL_SCROLLBAR) > 0) {
			if ((hints & IViewModel.VERTICAL_SCROLLBAR) > 0) {
				return prefixStyleName.addSuffix("scroll");
			}

			return prefixStyleName.addSuffix("horizontal-scroll");
		}

		return prefixStyleName.addSuffix("vertical-scroll");
	}

	public CssStyle getScrollableTableContainerCssStyle() {
		if (scrollableTableContainerCssStyle == null) {
			scrollableTableContainerCssStyle = CssStyle
					.create(DEFAULT_SCROLLABLE_TABLE_CONTAINER_STYLE_NAME);
		}

		return scrollableTableContainerCssStyle;
	}

	public CssStyle getHeaderCssStyle(IHeaderModel headerModel) {

		CssStyle styleName = getDefaultHeaderStyleName();

		int viewHints = headerModel.getViewModel().getRenderHints();

		if ((viewHints & (IViewModel.HORIZONTAL_SCROLLBAR | IViewModel.VERTICAL_SCROLLBAR)) == 0) {
			styleName = styleName.addSuffix("no-scroll");

		} else {
			styleName = styleName.addSuffix("scroll");
		}

		return styleName;
	}

	protected CssStyle getDefaultHeaderStyleName() {
		if (headerCssStyle == null) {
			headerCssStyle = CssStyle
					.create(DEFAULT_HORIZONTAL_HEADER_STYLE_NAME);
		}
		return headerCssStyle;
	}

	protected CssStyle[] createRowStyleNames() {
		return new CssStyle[] { CssStyle.create(DEFAULT_ROW_STYLE_NAME) };
	}

	protected CssStyle getRowStyleNameByRenderedIndex(int renderedIndex) {
		if (rowCssStyles == null) {
			rowCssStyles = createRowStyleNames();
		}

		return rowCssStyles[renderedIndex % rowCssStyles.length];
	}

	protected boolean hasRowDifferentStyleNames() {
		return false;
	}

	public CssStyle getRowStyleName(IViewRenderContext viewRenderContext,
			IRowModel rowModel) {

		int renderedIndex = 0;

		if (hasRowDifferentStyleNames()) {
			renderedIndex = rowModel.getGroupModel().getGridModel()
					.getRowRenderedIndexRecorder().getRenderedIndex(rowModel);
		}

		CssStyle style = getRowStyleNameByRenderedIndex(renderedIndex);

		return computeStyleByMask(style, rowModel);
	}

	protected CssStyle getCellStyleNameByRenderedIndex(int rowRenderedIndex,
			int cellRenderedIndex) {
		if (cellCssStyles == null) {
			cellCssStyles = createCellStyleNames();
		}

		return cellCssStyles[cellRenderedIndex % cellCssStyles.length];
	}

	protected CssStyle[] createCellStyleNames() {
		return new CssStyle[] { CssStyle.create(DEFAULT_CELL_STYLE_NAME) };
	}

	protected boolean hasCellDifferentStyleNames() {
		return false;
	}

	public CssStyle getCellStyleName(IGridRenderContext gridRenderContext,
			ICellModel cellModel) {

		int rowRenderedIndex = 0;
		int cellRenderedIndex = 0;

		if (hasCellDifferentStyleNames()) {
			IRowModel rowModel = cellModel.getRowModel();
			IGridModel gridModel = rowModel.getGroupModel().getGridModel();

			rowRenderedIndex = gridModel.getRowRenderedIndexRecorder()
					.getRenderedIndex(rowModel);

			cellRenderedIndex = gridRenderContext.getColumnRenderedIndexes()[cellModel
					.getModelIndex()];
		}

		CssStyle style = getCellStyleNameByRenderedIndex(rowRenderedIndex,
				cellRenderedIndex);

		return computeStyleByMask(style, cellModel);
	}

	public CssStyle getGroupStyleName(IGridRenderContext gridRenderContext,
			IGroupModel groupModel) {
		if (groupCssStyle == null) {
			groupCssStyle = CssStyle.create(DEFAULT_GROUP_STYLE_NAME);
		}
		return computeStyleByMask(groupCssStyle, groupModel);
	}

	@Override
	public CssStyle getFocusedTitleRowCssStyle(ITitleRowModel titleRowModel) {
		if (focusedTitleRowCssStyle == null) {
			focusedTitleRowCssStyle = CssStyle
					.create(DEFAULT_FOCUSED_TITLE_ROW_STYLE_NAME);
		}
		return focusedTitleRowCssStyle;
	}

	public CssStyle getGroupTitleCssStyle(IGroupTitleModel groupTitleModel) {
		if (groupTitleCssStyle == null) {
			groupTitleCssStyle = CssStyle
					.create(DEFAULT_GROUP_TITLE_STYLE_NAME);
		}

		return computeStyleByMask(groupTitleCssStyle, groupTitleModel);
	}

	public CssStyle getTitleCellCssStyle(ITitleCellModel titleCellModel) {
		if (titleCellCssStyle == null) {
			titleCellCssStyle = CssStyle.create(DEFAULT_TITLE_CELL_STYLE_NAME);
		}

		CssStyle cssStyle = computeStyleByMask(titleCellCssStyle,
				titleCellModel);

		switch (titleCellModel.getColumnModel().getOrderingMask()) {
		case NONE:
			break;

		case ASCENDING:
			cssStyle = cssStyle.addSuffix(ASCENDING_SUFFIX);
			break;

		case DESCENDING:
			cssStyle = cssStyle.addSuffix(DESCENDING_SUFFIX);
			break;
		}

		return cssStyle;
	}

	@Override
	public CssStyle getTitleCellSizeDraggerCssStyle(
			ITitleCellModel titleCellModel) {
		if (titleCellSizeDraggerCssStyle == null) {
			titleCellSizeDraggerCssStyle = CssStyle
					.create(DEFAULT_TITLE_CELL_DRAGGER_STYLE_NAME);
		}
		return titleCellSizeDraggerCssStyle;
	}

	@Override
	public CssStyle getTitleCellOrderMarkerCssStyle(
			ITitleCellModel titleCellModel) {
		if (titleCellOrderMarkerCssStyle == null) {
			titleCellOrderMarkerCssStyle = CssStyle
					.create(DEFAULT_TITLE_CELL_ORDER_MARKER_STYLE_NAME);
		}

		return titleCellOrderMarkerCssStyle;
	}

	@Override
	public CssStyle getTitleCellPopupMarkerCssStyle(
			ITitleCellModel titleCellModel) {
		if (titleCellPopupMarkerCssStyle == null) {
			titleCellPopupMarkerCssStyle = CssStyle
					.create(DEFAULT_TITLE_CELL_POPUP_MARKER_STYLE_NAME);
		}

		return titleCellPopupMarkerCssStyle;
	}

	@Override
	public CssStyle getTitleCellTextCssStyle(ITitleCellModel titleCellModel) {
		if (titleCellTextCssStyle == null) {
			titleCellTextCssStyle = CssStyle
					.create(DEFAULT_TITLE_CELL_TEXT_STYLE_NAME);
		}

		return titleCellTextCssStyle;
	}

	public CssStyle getTitleRowCssStyle(ITitleRowModel titleRow) {
		if (titleRowCssStyle == null) {
			titleRowCssStyle = CssStyle.create(DEFAULT_TITLE_ROW_STYLE_NAME);
		}

		return computeStyleByMask(titleRowCssStyle, titleRow);
	}

	protected CssStyle computeStyleByMask(CssStyle style, IElementModel element) {
		int stateMask = element.getStateMask();

		if (stateMask == 0) {
			return style;
		}

		if ((stateMask & IStateMasks.CHECKED_STATE_MASK) > 0) {
			style = style.addSuffix(CHECKED_SUFFIX);
		}

		if ((stateMask & IStateMasks.SELECTED_STATE_MASK) > 0) {
			style = style.addSuffix(SELECTION_SUFFIX);
		}

		if ((stateMask & IStateMasks.ADDITIONAL_INFORMATION_STATE_MASK) > 0) {
			style = style.addSuffix(ADDITIONAL_INFORMATION_SUFIX);
		}

		if ((stateMask & IStateMasks.OVER_STATE_MASK) > 0) {
			style = style.addSuffix(HOVER_SUFFIX);
		}

		if ((stateMask & IStateMasks.FOCUS_STATE_MASK) > 0) {
			style = style.addSuffix(FOCUS_SUFFIX);
		}

		if ((stateMask & IStateMasks.ORDER_STATE_MASK) > 0) {
			style = style.addSuffix(ORDER_SUFFIX);
		}

		if ((stateMask & IStateMasks.CONTENT_FOCUSED_STATE_MASK) > 0) {
			style = style.addSuffix(CONTENT_FOCUSED_SUFFIX);
		}

		return style;
	}

	@Override
	public IGridModelController getGridModelController(IGridModel gridModel) {
		return new DefaultGridController();
	}

	@Override
	public IViewController getViewController(IViewModel viewModel) {
		if (viewModelController == null) {
			return DefaultViewController.SINGLETON;
		}
		return viewModelController;
	}

	public int getGridBorderWidth() {
		return 3;
	}

	public int[] getGridPaddings() {
		return GRID_PADDINGS;
	}

	public int[] getTableMargins() {
		return TABLE_MARGINS;
	}

	public int getDataTableCellPadding() {
		return 0;
	}

	public int getDataTableCellSpacing() {
		return 0;
	}

	public int getViewBorderWidth() {
		return 2;
	}

	public int getHorizontalHeaderHeight(IHeaderModel view) {
		return 20;
	}

	public int getVerticalHeaderWidth(IHeaderModel view) {
		return 20;
	}

	public int getHeaderSeparatorSize(IHeaderModel view) {
		return 0;
	}

	public int getMaximumVerticalScrollBarWidth() {
		return 32;
	}

	@Override
	public IOverProvider getOverProvider(IGridWidget gridWidget) {
		if (isOverSupported(gridWidget) == false) {
			return null;
		}
		return createDefaultOverProvider(gridWidget);
	}

	protected boolean isOverSupported(IGridWidget gridWidget) {
		return false;
	}

	@Override
	public IFocusProvider getFocusProvider(IGridWidget gridWidget) {
		return new BasicFocusProvider();
	}

	private IOverProvider createDefaultOverProvider(IGridWidget gridWidget) {
		return new BasicOverProvider();
	}

	@Override
	public void addElementEventControllers(
			List<IElementModelEventController> list, IGridWidget gridWidget) {
		list.add(new RowModelEventController());
		list.add(new TitleCellEventController());
	}

	@Override
	public IOrderProvider getColumnsOrderProvider(IGridWidget gridWidget) {
		return new BasicOrderProvider();
	}

}
